home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-04
/
ddj1291.zip
/
STAT.ZIP
/
SOURCE.ZIP
/
PARDMAP.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-09
|
13KB
|
413 lines
/*
** File: pardmap.c
**
** Copyright 1990
** Fred Motteler and Applied Microsystems Corporation
** All Rights Reserved
**
** Description: This file contains a generic link map (memory map) reader and
** the necessary support routines. A stand alone tester is
** included.
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include "padef.h"
/* This is a table of pointers to mapdata structures. */
struct padata *patableAHP[PAMAX];
/*
** Function: int pardmap( FILE *mapFP, FILE *formatFP,
** unsigned long originL, processedNP )
**
** Description: This is a generic map file reader.
**
** The map is contained in the file with file pointer mapFP.
**
** Format information about the map file is in the file with
** file pointer formatFP.
**
** The value of originL gives the offset of the map zero point
** relative to the start of memory. For MS-DOS and any system
** that relocates the executable image, this value is the start
** of the program in memory.
**
** The format of the map file is assumed to be:
**
** [[initial information to ignore]
** start of symbolic information identifier]
** symbolic information
** [end of symbolic information identifier
** [final information to ignore]]
**
** The format of the symbol information is assumed to be:
**
** symbol value
** or
** value symbol
**
** where value may be segmented.
**
** segment:offset
**
** or linear:
**
** value
**
** Information about the:
**
** "start of symbolic information identifier"
** "end of symbolic information identifier"
** symbol value order
** symbol line format
** lines to skip
**
** is given in the map format file in ASCII format:
**
** PA_START_ID:"string to look for to start symbolic info"
** PA_END_ID:"string to look for to end symbolic info"
** PA_ORDER:"sym val" (for linear address)
** "val sym"
** "sym seg:off" (for segmented address)
** "seg:off sym"
** PA_FORMAT:"scanf format string for reading values"
** PA_SKIP_ID:"string to look for on line to ignore"
**
** Note that map file lines containing the START_ID, END_ID,
** and SKIP_ID strings are not processed for symbolic information.
**
** The order and format fields are required to allow use of
** the ANSI sscanf() function.
**
** The entries in the map format file may be in any order.
**
** Upon exit, the maptableAHP array contains pointers to mapdata
** structures that contain address and symbol name information.
** The table is sorted according to absolute address value. Note
** that all segment:offset data is converted to linear address
** values.
**
** The location pointed to by processedNP is updated with the
** number of symbol processed.
**
** The returned value is zero if the map read operation was
** successful. Otherwise an error code is returned.
*/
int
pardmap(mapFP, formatFP, originL, processedNP)
FILE *mapFP; /* Map file to read */
FILE *formatFP; /* File with map file format information */
unsigned long originL; /* Program origin offset */
int *processedNP; /* Pntr to count of symbols processed */
{
unsigned long valueL; /* Value of current symbol */
unsigned int offsetW; /* Offset part of current symbol */
unsigned int segmentW; /* Offset part of current symbol */
char symbolAB[PA_LINE_LEN]; /* Current symbol string */
struct padata *tempHP; /* Temp pntr to map data structure */
char lineAB[PA_LINE_LEN]; /* Input line buffer */
int linelenN; /* Length of input line */
char startAB[PA_LINE_LEN]; /* Start line identifier */
char endAB[PA_LINE_LEN]; /* End line identifier */
char orderAB[PA_LINE_LEN]; /* Symbol value order string */
char formatAB[PA_LINE_LEN]; /* Symbol value format string */
char skip1AB[PA_LINE_LEN]; /* Skip line identifier */
char skip2AB[PA_LINE_LEN]; /* Skip line identifier */
int errorN; /* Error code */
int symorderN; /* Gives symbol value order and type */
int i; /* General index */
/* Read in map file delimiters from the map configuration file. */
if ((errorN = paconfig(formatFP, PA_START_ID, startAB)) != 0)
return(errorN);
if ((errorN = paconfig(formatFP, PA_END_ID, endAB)) != 0)
return(errorN);
if ((errorN = paconfig(formatFP, PA_ORDER, orderAB)) != 0)
return(errorN);
if ((errorN = paconfig(formatFP, PA_FORMAT, formatAB)) != 0)
return(errorN);
if ((errorN = paconfig(formatFP, PA_SKIP1_ID, skip1AB)) != 0)
return(errorN);
if ((errorN = paconfig(formatFP, PA_SKIP2_ID, skip2AB)) != 0)
return(errorN);
#ifdef TEST
printf(" start string: %s\n",startAB);
printf(" end string: %s\n",endAB);
printf(" order string: %s\n",orderAB);
printf("format string: %s\n",formatAB);
printf(" skip string: %s\n",skip1AB);
printf(" skip string: %s\n",skip2AB);
#endif
/* Determine the symbol value order and type. */
if (strcmp(PA_SV_ID,orderAB) == 0)
symorderN = PA_SYM_VAL;
else if (strcmp(PA_VS_ID,orderAB) == 0)
symorderN = PA_VAL_SYM;
else if (strcmp(PA_SSO_ID,orderAB) == 0)
symorderN = PA_SYM_SEG;
else if (strcmp(PA_SOS_ID,orderAB) == 0)
symorderN = PA_SEG_SYM;
else
return(PA_BAD_ORDER_E);
/* Skip initial part of map file that is not used. */
if (startAB[0] != '\0')
{
while (fgets(lineAB, PA_LINE_LEN, mapFP) != (char *) NULL)
{
/* Search the line for the string in startAB that starts
* the map data. */
if (strstr(lineAB, startAB) != (char *) NULL)
break;
}
}
/* Initialize the number of address/symbol pairs processed. */
*processedNP = 0;
patableAHP[0] = (struct padata *) NULL;
/* Read symbol section of the map file */
while (fgets(lineAB, PA_LINE_LEN, mapFP) != (char *) NULL)
{
/* Check if the line is blank */
linelenN = strlen(lineAB);
for (i = 0; i < linelenN; i++)
{
if (isalnum(lineAB[i]))
break;
}
if (i == linelenN)
continue;
/* Search line for the string endAB that ends the map data. */
if ((endAB[0] != '\0') && (strstr(lineAB, endAB) != (char *) NULL))
break;
/* Search line for either string skip1AB or skip2AB that indicate
* the line is to be skipped. */
if ((skip1AB[0] != '\0') && (strstr(lineAB, skip1AB) != (char *) NULL))
continue;
if ((skip2AB[0] != '\0') && (strstr(lineAB, skip2AB) != (char *) NULL))
continue;
#ifdef TEST
printf("Line to process: %s\n",lineAB);
#endif
/* The line is ok, process the symbol data that it contains. */
switch(symorderN)
{
case PA_SYM_VAL:
/* Symbol / linear value format - note that valueL is a long! */
if (sscanf(lineAB,formatAB,symbolAB,&valueL) != 2)
{
/* In some situations (Intermetrics), the symbol value may
* be on one line, and the rest of the value information is
* on the next line. Try appending the next line to the
* current line, and then retry the operation. */
for (i = 0; !iscntrl(lineAB[i]); i++);
if (fgets((&(lineAB[i])), PA_LINE_LEN, mapFP) != (char *) NULL)
{
if (sscanf(lineAB,formatAB,symbolAB,&valueL) != 2)
return(PA_MAP_FMT_E);
}
else
return(PA_MAP_FMT_E);
}
valueL += originL;
break;
case PA_VAL_SYM:
/* Linear value / symbol format - note that valueL is a long! */
if (sscanf(lineAB,formatAB,&valueL,symbolAB) != 2)
return(PA_MAP_FMT_E);
valueL += originL;
break;
case PA_SYM_SEG:
/* Symbol / segmented value format - note that segmentW and
* offsetW are ints! */
if (sscanf(lineAB,formatAB,symbolAB,&segmentW,&offsetW) != 3)
return(PA_MAP_FMT_E);
valueL = (unsigned long) segmentW;
valueL <<= 4;
valueL += (unsigned long) offsetW;
valueL += originL;
break;
case PA_SEG_SYM:
/* Segmented value / symbol format - note that segmentW and
* offsetW are ints! */
if (sscanf(lineAB,formatAB,&segmentW,&offsetW,symbolAB) != 3)
return(PA_MAP_FMT_E);
valueL = (unsigned long) segmentW;
valueL <<= 4;
valueL += (unsigned long) offsetW;
valueL += originL;
break;
default:
return(PA_BAD_ORDER_E);
}
/* Check if the symbol starts with a numeric digit. If so, then
* throw the symbol entry out. */
if (isdigit((symbolAB[0])))
continue;
/* A valid symbol value is in valueL, and a valid symbol name
* is in symbolAB, check if we have room in the table for this
* entry. The extra three is to allow room for a "beginning of
* memory symbol", an "end of memory symbol" and a NULL pointer
* table terminator. */
if ((*processedNP) >= (PAMAX - 3))
return(PA_TAB_FULL_E);
/* There is room, allocate space for the actual symbol info. */
if ((tempHP = (struct padata *) malloc (sizeof(struct padata)))
== (struct padata *) NULL)
return(PA_NO_MEM_E);
/* Enter the symbol into the table. */
patableAHP[((*processedNP)++)] = tempHP;
patableAHP[(*processedNP)] = (struct padata *) NULL;
tempHP->addressL = valueL;
strncpy( tempHP->symbolAB, symbolAB, (PA_SYM_LEN - 1));
(tempHP->symbolAB)[PA_SYM_LEN - 1] = '\0';
tempHP->hitsL = 0L;
#ifdef TEST
printf("Adding %d: %s with value %lx\n", (*processedNP),
tempHP->symbolAB, tempHP->addressL );
#endif
}
/* Enter beginning of memory symbol if there is room. Allocate space for
* the actual symbol info. */
if ((tempHP = (struct padata *) malloc (sizeof(struct padata)))
== (struct padata *) NULL)
return(PA_NO_MEM_E);
patableAHP[((*processedNP)++)] = tempHP;
patableAHP[(*processedNP)] = (struct padata *) NULL;
tempHP->addressL = 0L;
strncpy( tempHP->symbolAB, PA_BOMSYM, (PA_SYM_LEN - 1));
(tempHP->symbolAB)[PA_SYM_LEN - 1] = '\0';
tempHP->hitsL = 0L;
/* Enter end of memory symbol if there is room. Allocate space for
* the actual symbol info. */
if ((tempHP = (struct padata *) malloc (sizeof(struct padata)))
== (struct padata *) NULL)
return(PA_NO_MEM_E);
patableAHP[((*processedNP)++)] = tempHP;
patableAHP[(*processedNP)] = (struct padata *) NULL;
tempHP->addressL = PA_68020_TOP;
strncpy( tempHP->symbolAB, PA_TOPSYM, (PA_SYM_LEN - 1));
(tempHP->symbolAB)[PA_SYM_LEN - 1] = '\0';
tempHP->hitsL = 0L;
#ifdef TEST
printf("Dump of unsorted table\n");
for (i = 0; i < *processedNP; i++)
{
printf("%s %lx\n",
((patableAHP[i])->symbolAB), ((patableAHP[i])->addressL));
}
printf("Number of symbols to sort: %d\n", *processedNP);
printf("Size of each pointer to a symbol record %d\n", sizeof(struct padata *));
#endif
/* The map file has been read in, now sort it according to value. */
qsort(&(patableAHP[0]), *processedNP, sizeof(struct padata *), pa_addrcomp );
/* Ok termination, return zero as a success code. The number of symbols
* read in is returned via *processedNP. */
return(0);
}
/*
** Function: void paclear();
**
** This function frees all memory allocated in the process of making a map
** table.
*/
void
paclear()
{
int i;
i = 0;
while ( patableAHP[i] != (struct padata *) NULL )
{
free( patableAHP[i] );
patableAHP[i++] = (struct padata *) NULL;
}
return;
}
#ifdef TEST
/*
** Function: int main( argcN, argvAS )
**
** Description: This is a standalone tester to allow testing the map file
** reader.
*/
int
main( argcN, argvAS )
int argcN;
char *argvAS[];
{
FILE *mapFP; /* File pointer to map file */
FILE *formatFP; /* File pointer to map config. file */
int i;
int processedN;
unsigned long originL; /* Origin of program in memory
* relative to map values. */
int errorN; /* Error code */
printf("pardmap - Trial linker/memory map test reader program\n");
printf("Version %s\n", PA_VERSION);
printf("Copyright (C) 1990 Fred Motteler and Applied Microsystems Corporation\n");
if (argcN != 4)
{
printf("Usage: pardmap origin_offset filename.cfg filename.map\n");
printf(" Where: origin_offset program origin offset\n");
printf(" filename.cfg map file configuration file\n");
printf(" filename.map map file\n");
exit(-100);
}
if ((mapFP = fopen(argvAS[3], "r")) == (FILE *) NULL)
{
printf("Unable to open map file\n");
exit(-101);
}
if ((formatFP = fopen(argvAS[2], "r")) == (FILE *) NULL)
{
printf("Unable to open map configuration file\n");
exit(-102);
}
sscanf(argvAS[1], "%lx", &originL);
if ((errorN = pardmap(mapFP, formatFP, originL, &processedN)) != 0)
{
pa_error(errorN);
exit(errorN);
}
printf("Number of symbols processed: %d\n", processedN);
printf("Dump of sorted table\n");
for (i = 0; i < processedN; i++)
{
printf("%s %lx %ld\n",
((patableAHP[i])->symbolAB),
((patableAHP[i])->addressL),
((patableAHP[i])->hitsL));
}
paclear();
exit(0);
}
#endif